//
//  NetworkTools.swift
//  weibo-01
//
//  Created by 韩家奇 on 15/11/6.
//  Copyright © 2015年 hanjiaqi. All rights reserved.
//

import UIKit
import AFNetworking
// 请求方法枚举
enum requestMethod: String {
    case GET = "GET"
    case POST = "POST"
}

class NetworkTools: AFHTTPSessionManager {
    
    //网络请求回调  和OC中的起别名相似
    typealias requestBack = (result: AnyObject?, error: NSError?)->()
    
// MARK: - 应用程序信息
//    private let appKey = "3863118655"
     private let appKey = "1037379085"
     private let appSecret = "825b1665cb0156d91e3a78a1c1d77f02"
//    private let appSecret = "b94c088ad2cdae8c3b9641852359d28c"
    private let redirectUrl = "http://www.baidu.com"
    
    //单例
    static let sharedTools:NetworkTools = {
        let tools = NetworkTools(baseURL: nil)
        //设置反序列化格式
        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
        return tools
    }()
}
// MARK: - 发布微博
extension NetworkTools {
//    func sendStatus (status: String, finished: requestBack) {
        /// - see: [http://open.weibo.com/wiki/2/statuses/upload](http://open.weibo.com/wiki/2/statuses/upload)
        func sendStatus(status: String, image: UIImage?, finished: requestBack) {


        //1.创建参数字典
        var params = [String: AnyObject]()
        //设置参数
        params["status"] = status
//        let urlString = "https://api.weibo.com/2/statuses/update.json"
            
        // 3. 发起网络请求
//        tokenRequest(.POST, URLString: urlString, parameters: params, finished: finished)
            // 3. 判断是否上传图片
            if image == nil {
                let urlString = "https://api.weibo.com/2/statuses/update.json"
                
                tokenRequest(.POST, URLString: urlString, parameters: params, finished: finished)
            } else {
                let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
                
                let data = UIImagePNGRepresentation(image!)
                
                upload(urlString, data: data!, name: "pic", parameters: params, finished: finished)
            }

    }
}
// MARK: - 微博数据相关方法

extension NetworkTools {
    /// 加载微博数据
    ///
    /// - parameter since_id: 若指定参数,则返回ID 比since_id大的微博(即比since_id时间晚的微博)默认为0
    /// - parameter max_id:   若指定参数,则返回id小于或等于max_id的微博 默认为0
    /// - parameter finished: 完成回调
    func loadStatus(since_id since_id: Int, max_id: Int, finished: requestBack) {
        
        // 1. 创建参数字典
        var params = [String: AnyObject]()
        
        // 判断是否下拉
        if since_id > 0 {
            params["since_id"] = since_id
        } else if max_id > 0 {  // 上拉参数
            params["max_id"] = max_id - 1
        }
        
        // 2. 准备网络参数
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        // 3. 发起网络请求
        tokenRequest(.GET, URLString: urlString, parameters: params, finished: finished)
    }
}

// MARK: - 用户相关方法
extension NetworkTools {
    
    /// 加载用户信息
    ///
    /// - parameter uid:         uid
    /// - parameter finished:    完成回调
    /// - see: [http://open.weibo.com/wiki/2/users/show](http://open.weibo.com/wiki/2/users/show)
    func loadUserInfo(uid: String, finished: requestBack) {
        
        // 1. 创建参数字典
        var params = [String: AnyObject]()
        
        // 2. 处理网络参数
        let urlString = "https://api.weibo.com/2/users/show.json"
        
        params["uid"] = uid
        
        tokenRequest(.GET, URLString: urlString, parameters: params, finished: finished)
    }
}



// MARK: - OAuth 相关方法
extension NetworkTools {
    
    /// OAuth 授权 URL
    /// - see: [http://open.weibo.com/wiki/Oauth2/authorize](http://open.weibo.com/wiki/Oauth2/authorize)
    var oauthURL: NSURL {
        
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(appKey)&redirect_uri=\(redirectUrl)"
        
        return NSURL(string: urlString)!
    }
    
    /// 加载 AccessToken
    func loadAccessToken(code: String, finished: requestBack) {
        
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        let params = ["client_id": appKey,
            "client_secret": appSecret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirectUrl]
        
        request(.POST, URLString: urlString, parameters: params, finished: finished)
        // 测试返回的数据内容 - AFN 默认的响应格式是 JSON，会直接反序列化
        // 如果要确认数据格式的问题
        // 如果是 NSNumber，则没有引号！在做 KVC 指定属性类型非常重要！
        
    }
}
// MARK: - 封装 AFN 网络方法
extension NetworkTools {
    
    private func appendToken(inout parameters:[String: AnyObject]?) ->Bool {
        //1.token是否为nil
        guard let token = UserAccountViewModel.sharedUserAccount.accessToken else {
            return false
        }
        //2.判断参数字典有否有值
        if parameters == nil  {
            parameters = [String: AnyObject]()
        }
        //3.设置token
        parameters!["access_token"] = token
        return true
    }
    /// 使用 token 进行网络请求
    ///
    /// - parameter method:     GET / POST
    /// - parameter URLString:  URLString
    /// - parameter parameters: 参数字典
    /// - parameter finished:   完成回调
    private func tokenRequest(method: requestMethod, URLString: String, var parameters: [String: AnyObject]?, finished: requestBack) {
        
        // 1. 设置 token 参数 －> 将 token 添加到 parameters 字典中
        // 判断 token 是否有效
//        guard let token = UserAccountViewModel.sharedUserAccount.accessToken else {
        //1.如果追加token失败,直接返回
        if !appendToken(&parameters) {
        // token 无效
            // 如果字典为 nil，通知调用方，token 无效
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token 为空"]))
            
            return
        }
        
        // 设置 parameters 字典
//        // 1> 判断参数字典是否有值
//        if parameters == nil {
//            parameters = [String: AnyObject]()
//        }
//        
//        parameters!["access_token"] = token
        
        // 2. 发起网络请求
        request(method, URLString: URLString, parameters: parameters, finished: finished)
    }
    
    /// 网络请求
    ///
    /// - parameter method:     GET / POST
    /// - parameter URLString:  URLString
    /// - parameter parameters: 参数字典
    /// - parameter finished:   完成回调
    private func request(method: requestMethod, URLString: String, parameters: [String: AnyObject]?, finished: requestBack) {
        
        // 定义成功回调
        let success = { (task: NSURLSessionDataTask?, result: AnyObject) -> Void in
            finished(result: result, error: nil)
        }
        
        // 定义失败回调
        let failure = { (task: NSURLSessionDataTask?, error: NSError) -> Void in
            // 在开发网络应用的时候，错误不要提示给用户，但是错误一定要输出！
            print(error)
            finished(result: nil, error: error)
        }
        if method == requestMethod.GET{
            GET(URLString, parameters: parameters, success: success, failure: failure)
            
        }else{
            POST(URLString, parameters: parameters, success: success, failure: failure)
        }
    }
    /// 上传文件
    
    /// 上传文件
    private func upload(URLString: String, data: NSData, name: String, var parameters: [String: AnyObject]?, finished: requestBack) {
        // 设置 token 字典
        // 1. 设置 token 参数 －> 将 token 添加到 parameters 字典中
        // 判断 token 是否有效
//        guard let token = UserAccountViewModel.sharedUserAccount.accessToken else {
//      //1.如果追加token失败 直接返回
        if !appendToken(&parameters){
        // token 无效
            // 如果字典为 nil，通知调用方，token 无效
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token 为空"]))
            
            return
        }
        
        // 设置 parameters 字典
        // 1> 判断参数字典是否有值
//        if parameters == nil {
//            parameters = [String: AnyObject]()
//        }
//        
//        parameters!["access_token"] = token

        
        /**
        1. data 要上传文件的二进制数据
        2. name 是服务器定义的字段名称 － 后台接口文档会提示
        3. fileName 是保存在服务器的文件名，但是：现在通常可以`乱写`，后台会做后续的处理
        - 根据上传的文件，生成 缩略图，中等图，高清图
        - 保存在不同路径，并且自动生成文件名
        
        - fileName 是 HTTP 协议定义的属性
        4. mimeType / contentType: 客户端告诉服务器，二进制数据的准确类型
        - 大类型/小类型
        * image/jpg image/gif image/png
        * text/plain text/html
        * application/json
        - 无需记忆
        - 如果不想告诉服务器准确的类型
        * application/octet-stream
        */
        POST(URLString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
            
            formData.appendPartWithFileData(data, name: name, fileName: "xxx", mimeType: "application/octet-stream")
            
            }, success: { (_, result) -> Void in
                finished(result: result, error: nil)
            }) { (_, error) -> Void in
                print(error)
                finished(result: nil, error: error)
        }
    }
}

